package com.fourth.utils;

import com.google.common.base.CaseFormat;
import org.apache.commons.beanutils.BeanUtils;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.util.ArrayList;
import java.util.List;

/**
 * @Author CZQ
 * @Date 2022/7/30 15:50
 * @Version 1.0
 *
 * 封装为任何JDBC数据库的任何查询都可以使用该工具类的方法
 *
 *  id为主键
 *  select count(*) from t;               单行单列
 *  select * from t where id ='1001';      单行多列
 *  select count(*) from t group by tm_id;  多行单列
 *  select * from t;   多行多列
 *
 */
public class JdbcUtil {

    /**
     *
     * @param connection  连接
     * @param sql  sql语句
     * @param clz   要有一个<T>对象的封装类型 才能构建<T>对象
     * @param underScoreToCamel  下划线向驼峰之间的转换  因为在SQL中往往用的都是下划线，在JavaBean中往往用的都是驼峰命名  source_table -> sourceTable
     * @param <T> 泛型的对象
     * @return
     */
    public static <T> List<T> queryList(Connection connection,String sql,Class<T> clz, boolean underScoreToCamel) throws Exception {
        //1.创建集合用于存放结果数据
        ArrayList<T> list = new ArrayList<>();
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;

        try {
            //2.预编译SQL
            preparedStatement  = connection.prepareStatement(sql);

            //3.执行SQL查询
             resultSet = preparedStatement.executeQuery();

            //4.遍历查询结果集，将每行数据封装成T对象并放入集合

            ResultSetMetaData metaData = resultSet.getMetaData();
            int columnCount = metaData.getColumnCount();
            // 4.1 行遍历
            while (resultSet.next()) {
                //构建T对象
                T t = clz.newInstance();

                // 4.2 列遍历
                for (int i = 0; i < columnCount ; i++) {
                    String columnName = metaData.getColumnName(i + 1);

                    //通过列名来获取值
                    Object value = resultSet.getObject(columnName);

                    //构建一个T对象 把获取的值放进去 但是考虑到是一行一行的放进去的，所以要把T对象的构建要放在行遍历里，列遍历外
                    if (underScoreToCamel){
                        columnName = CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL,columnName.toLowerCase());
                    }
                    // 因为t 没有get\set方法，所以要借助一个工具类来实现set功能
                    BeanUtils.setProperty(t,columnName, value);
                }

                // 将T对象加入集合
                list.add(t);

            }
        } finally {

            if (resultSet != null){
                resultSet.close();
            }
            if (preparedStatement !=null){
                preparedStatement.close();
            }

        }

        //5. 返回结果
        return list;
    }


}
